/*

Frequency of use: 1 2 3 [4] 5 MEDIUM HIGH

Short:
    Composite combines several classes into a single class.

Long:
    In computer science, the composite pattern is a partitioning design pattern. 
Composite allows a group of objects to be treated in the same way as a single 
instance of an object. The intent of composite is to "compose" objects into tree 
structures to represent part-whole hierarchies. Composite lets clients treat 
individual objects and compositions uniformly.[1]

Information sources:
 - http://calumgrant.net/patterns/index.html
 - http://en.wikipedia.org/wiki/Composite_pattern
 - http://www.dofactory.com/Patterns/Patterns.aspx
*/

#include <iostream>
#include <string>

class Greeting
{
public:
	virtual ~Greeting() { }
	virtual std::string get_greeting()=0;
};

class Recipient
{
public:
	virtual ~Recipient() { }
	virtual std::string get_recipient()=0;
};

class Composite
{
	Greeting & greeting;
	Recipient & recipient;
public:
	Composite(Greeting & greeting, Recipient & recipient) :
	    greeting(greeting),
		recipient(recipient) { }
	void greet() const
	{
		std::cout << greeting.get_greeting() << " " 
			<< recipient.get_recipient() << "!" << std::endl;
	}
};

class Hello : public Greeting
{
public:
	std::string get_greeting() { return "Hello"; }
};

class World : public Recipient
{
public:
	std::string get_recipient() { return "world"; }
};

void hello_world(const Composite & composite)
{
	composite.greet();
}

int main()
{
	Hello hello;
	World world;
	hello_world(Composite(hello, world));
	return 0;
}
